package com.telit.firecommand.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.telit.common.dto.DistrictDTO;
import com.telit.common.entity.PageData;
import com.telit.common.exception.ForestBaseException;
import com.telit.firecommand.dao.GeoXzqhCunDao;
import com.telit.firecommand.entity.GeoXzqhCun;
import com.telit.firecommand.service.DistrictService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.Validate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * 行政区划
 *
 * @author yuezhuang
 * @date 2022-09-05
 */
@Slf4j
@Service
public class DistrictServiceImpl implements DistrictService {

    @Autowired
    private GeoXzqhCunDao geoXzqhCunDao;


    /**
     * 获取所有子行政区树
     *
     * @param districtCode 父类code
     *
     * @return DistrictDTO
     */
    @Override
    public List<DistrictDTO> qryAllByParentCode(String districtCode) {
        return null;
    }

    /**
     * 依据上级行政区划编码查询下级行政区划列表（分页）
     *
     * @param districtCode       上级行政区划编码
     * @param rank               行政区划层级, 1-省 2-市 3-区县 4-乡镇 5-村
     * @param defaultCurrentRank 是否默认为当前级别，否则默认查询子集
     *
     * @return DistrictDTO
     */
    @Override
    public PageData<List<DistrictDTO>> qryListByParentCodeWithPage(String districtCode, Integer rank,
                                                                   boolean defaultCurrentRank, Integer current,
                                                                   Integer size, boolean noPage) {
        if (rank != null) {
            Validate.isTrue(rank >= 0 && rank <= 5, "非法参数！");
        }
        int districtCodeLength = districtCode.length();
        String groupByName = null;
        String conditionName = null;
        String selectName = null;
        String countName = null;
        if (districtCodeLength == 2) {
            //省
            if (rank != null) {
                if (rank == 1) {
                    groupByName = "sheng,sheng_name";
                    countName = "sheng";
                } else if (rank == 2) {
                    groupByName = "sheng,sheng_name,shi,shi_name";
                    countName = "shi";
                } else if (rank == 3) {
                    groupByName = "sheng,sheng_name,shi,shi_name,xian,xian_name";
                    countName = "xian";
                } else if (rank == 4) {
                    groupByName = "sheng,sheng_name,shi,shi_name,xian,xian_name,xiang,xiang_name";
                    countName = "xiang";
                } else if (rank == 5) {
                    groupByName = "sheng,sheng_name,shi,shi_name,xian,xian_name,xiang,xiang_name,cun,cun_name";
                    countName = "cun";
                } else {
                    if (defaultCurrentRank) {
                        rank = 1;
                        groupByName = "sheng,sheng_name";
                        countName = "sheng";
                    } else {
                        rank = 2;
                        groupByName = "sheng,sheng_name,shi,shi_name";
                        countName = "shi";
                    }
                }
            } else {
                if (defaultCurrentRank) {
                    rank = 1;
                    groupByName = "sheng,sheng_name";
                    countName = "sheng";
                } else {
                    rank = 2;
                    groupByName = "sheng,sheng_name,shi,shi_name";
                    countName = "shi";
                }
            }
            conditionName = "sheng";
        } else if (districtCodeLength == 4) {
            //市
            if (rank != null) {
                if (rank == 2) {
                    groupByName = "sheng,sheng_name,shi,shi_name";
                    countName = "shi";
                } else if (rank == 3) {
                    groupByName = "sheng,sheng_name,shi,shi_name,xian,xian_name";
                    countName = "xian";
                } else if (rank == 4) {
                    groupByName = "sheng,sheng_name,shi,shi_name,xian,xian_name,xiang,xiang_name";
                    countName = "xiang";
                } else if (rank == 5) {
                    groupByName = "sheng,sheng_name,shi,shi_name,xian,xian_name,xiang,xiang_name,cun,cun_name";
                    countName = "cun";
                } else {
                    if (defaultCurrentRank) {
                        rank = 2;
                        groupByName = "sheng,sheng_name,shi,shi_name";
                        countName = "shi";
                    } else {
                        rank = 3;
                        groupByName = "sheng,sheng_name,shi,shi_name,xian,xian_name";
                        countName = "xian";
                    }
                }
            } else {
                if (defaultCurrentRank) {
                    rank = 2;
                    groupByName = "sheng,sheng_name,shi,shi_name";
                    countName = "shi";
                } else {
                    rank = 3;
                    groupByName = "sheng,sheng_name,shi,shi_name,xian,xian_name";
                    countName = "xian";
                }
            }
            conditionName = "shi";
        } else if (districtCodeLength == 6) {
            //县
            if (rank != null) {
                if (rank == 3) {
                    groupByName = "sheng,sheng_name,shi,shi_name,xian,xian_name";
                    countName = "xian";
                } else if (rank == 4) {
                    groupByName = "sheng,sheng_name,shi,shi_name,xian,xian_name,xiang,xiang_name";
                    countName = "xiang";
                } else if (rank == 5) {
                    groupByName = "sheng,sheng_name,shi,shi_name,xian,xian_name,xiang,xiang_name,cun,cun_name";
                    countName = "cun";
                } else {
                    if (defaultCurrentRank) {
                        rank = 3;
                        groupByName = "sheng,sheng_name,shi,shi_name,xian,xian_name";
                        countName = "xian";
                    } else {
                        rank = 4;
                        groupByName = "sheng,sheng_name,shi,shi_name,xian,xian_name,xiang,xiang_name";
                        countName = "xiang";
                    }
                }
            } else {
                if (defaultCurrentRank) {
                    rank = 3;
                    groupByName = "sheng,sheng_name,shi,shi_name,xian,xian_name";
                    countName = "xian";
                } else {
                    rank = 4;
                    groupByName = "sheng,sheng_name,shi,shi_name,xian,xian_name,xiang,xiang_name";
                    countName = "xiang";
                }
            }
            conditionName = "xian";
        } else if (districtCodeLength == 9) {
            //乡
            if (rank != null) {
                if (rank == 4) {
                    groupByName = "sheng,sheng_name,shi,shi_name,xian,xian_name,xiang,xiang_name";
                    countName = "xiang";
                } else {
                    if (defaultCurrentRank) {
                        rank = 4;
                        groupByName = "sheng,sheng_name,shi,shi_name,xian,xian_name,xiang,xiang_name";
                        countName = "xiang";
                    } else {
                        rank = 5;
                        groupByName = "sheng,sheng_name,shi,shi_name,xian,xian_name,xiang,xiang_name,cun,cun_name";
                        countName = "cun";
                    }
                }
            } else {
                if (defaultCurrentRank) {
                    rank = 4;
                    groupByName = "sheng,sheng_name,shi,shi_name,xian,xian_name,xiang,xiang_name";
                    countName = "xiang";
                } else {
                    rank = 5;
                    groupByName = "sheng,sheng_name,shi,shi_name,xian,xian_name,xiang,xiang_name,cun,cun_name";
                    countName = "cun";
                }
            }
            conditionName = "xiang";
        } else if (districtCodeLength == 12) {
            //村
            return null;
        }
        selectName = groupByName;

        if (noPage) {
            size = Integer.MAX_VALUE;
        }
        Integer offset = (current - 1) * size;


        StringBuffer countSql = new StringBuffer("select count(distinct ");
        countSql.append(countName);
        countSql.append(" ) ");
        countSql.append(" from geo_xzqh_cun ");
        countSql.append(" where ");
        countSql.append(conditionName);
        countSql.append(" = '");
        countSql.append(districtCode);
        countSql.append("' ");

        StringBuffer querySql = new StringBuffer("select ");
        querySql.append(selectName);
        querySql.append(" from geo_xzqh_cun ");
        querySql.append(" where ");
        querySql.append(conditionName);
        querySql.append(" = '");
        querySql.append(districtCode);
        querySql.append("' ");
        querySql.append(" group by ");
        querySql.append(groupByName);
        querySql.append(" limit ");
        querySql.append(size);
        querySql.append(" offset ");
        querySql.append(offset);

        long total = geoXzqhCunDao.countByCode(countSql.toString());
        if (total == 0) {
            return PageData.<List<DistrictDTO>>builder()
                    .count((int) total)
                    .size(size)
                    .current(current)
                    .datas(new ArrayList<>())
                    .build();
        }

        List<GeoXzqhCun> geoXzqhCuns = geoXzqhCunDao.selectByCode(querySql.toString());
        List<DistrictDTO> children = new ArrayList<>();
        Integer finalRank = rank;
        geoXzqhCuns.forEach(cun -> {
            String childName = null;
            String childCode = null;
            String parentCode = null;
            if (finalRank == 2) {
                childName = cun.getShiName();
                childCode = cun.getShi();
                parentCode = cun.getSheng();
            } else if (finalRank == 3) {
                childName = cun.getXianName();
                childCode = cun.getXian();
                parentCode = cun.getShi();
            } else if (finalRank == 4) {
                childName = cun.getXiangName();
                childCode = cun.getXiang();
                parentCode = cun.getXian();
            } else if (finalRank == 5) {
                childName = cun.getCunName();
                childCode = cun.getCun();
                parentCode = cun.getXiang();
            }
            children.add(DistrictDTO.builder()
                    .id(null)
                    .code(childCode)
                    .name(childName)
                    .parentCode(parentCode)
                    .build());
        });

        return PageData.<List<DistrictDTO>>builder()
                .count((int) total)
                .size(size)
                .current(current)
                .datas(children)
                .build();
    }

    /**
     * 依据上级行政区划编码查询下级行政区划列表
     *
     * @param districtCode 上级行政区划编码
     * @param rank         行政区划层级, 1-省 2-市 3-区县 4-乡镇 5-村
     *
     * @return DistrictDTO
     */
    @Override
    public List<DistrictDTO> qryListByParentCode(String districtCode, Integer rank) {
        return qryListByParentCodeWithPage(districtCode, rank, false, 1, 20, true).getDatas();
    }

    /**
     * 依据行政区划编码查询所属行政区划信息
     *
     * @param districtCode 行政区划编码
     *
     * @return DistrictDTO
     */
    @Override
    public DistrictDTO qryDistrictInfo(String districtCode) {
        String shengCode = null;
        String shiCode = null;
        String xianCode = null;
        String xiangCode = null;
        String cunCode = null;
        int childCodeLength = 0;//子行政区划长度
        String groupByName = null;//查询子行政区划，分组的字段
        int districtCodeLength = districtCode.length();
        if (districtCodeLength == 2) {
            shengCode = districtCode;
            groupByName = "sheng,sheng_name,shi,shi_name";
            childCodeLength = 4;
        } else if (districtCodeLength == 4) {
            shiCode = districtCode;
            groupByName = "sheng,sheng_name,shi,shi_name,xian,xian_name";
            childCodeLength = 6;
        } else if (districtCodeLength == 6) {
            xianCode = districtCode;
            groupByName = "sheng,sheng_name,shi,shi_name,xian,xian_name,xiang,xiang_name";
            childCodeLength = 9;
        } else if (districtCodeLength == 9) {
            xiangCode = districtCode;
            groupByName = "sheng,sheng_name,shi,shi_name,xian,xian_name,xiang,xiang_name,cun,cun_name";
        } else {
            cunCode = districtCode;
        }
        GeoXzqhCun geoXzqhCun = geoXzqhCunDao.selectByCondition(shengCode, shiCode, xianCode, xiangCode, cunCode);
        if (geoXzqhCun == null) {
            throw new ForestBaseException("未查询到该行政区划，请稍后再试！");
        }
        //行政区划名称
        String districtName = null;
        if (districtCodeLength == 2) {
            districtName = geoXzqhCun.getShengName();
        } else if (districtCodeLength == 4) {
            districtName = geoXzqhCun.getShiName();
        } else if (districtCodeLength == 6) {
            districtName = geoXzqhCun.getXianName();
        } else if (districtCodeLength == 9) {
            districtName = geoXzqhCun.getXiangName();
        } else {
            districtName = geoXzqhCun.getCunName();
        }
        DistrictDTO current = DistrictDTO.builder()
                .id(null)
                .code(districtCode)
                .name(districtName)
                .parentCode(null)
                .build();
        return current;
    }

    /**
     * 查询树形列表
     *
     * @param districtCode 行政区划编码
     *
     * @return DistrictDTO
     */
    @Override
    public DistrictDTO treeDistrict(String districtCode) {
        List<DistrictDTO> districtDTOS = geoXzqhCunDao.treeDistrict(districtCode);
        List<DistrictDTO> dto = buildTree(districtDTOS);
        if (CollectionUtil.isNotEmpty(dto)) {
            return dto.get(0);
        }
        return null;
    }

    public List<DistrictDTO> buildTree(List<DistrictDTO> list) {
        Map<String, DistrictDTO> map = new HashMap<>();
        List<DistrictDTO> trees = new ArrayList<>();
        list.forEach(districtDTO -> {
            map.put(districtDTO.getCode(), districtDTO);
        });

        list.forEach(districtDTO -> {
            DistrictDTO parent = map.get(districtDTO.getParentCode());
            if (parent != null) {
                List<DistrictDTO> children = parent.getChildren();
                if (children == null) {
                    children = new ArrayList<>();
                }
                children.add(districtDTO);
                parent.setChildren(children);
            } else {
                trees.add(districtDTO);
            }
        });
        return trees;
    }

}
